﻿using Bing.Maps;
using BingMapsRESTService.Common.JSON;
using System;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace BingMapsSearch_WinRT_CS
{
    public sealed partial class MainPage : Page
    {
        #region Private Properties

        private MapShapeLayer routeLayer;

        #endregion

        #region Constructor

        public MainPage()
        {
            this.InitializeComponent();

            routeLayer = new MapShapeLayer();
            MyMap.ShapeLayers.Add(routeLayer);
        }

        #endregion

        #region Button Handlers

        private void ClearMapBtn_Click(object sender, RoutedEventArgs e)
        {
            ClearMap();
        }

        private async void GeocodeBtn_Click(object sender, RoutedEventArgs e)
        {
            ClearMap();

            string query = GeocodeTbx.Text;

            if (!string.IsNullOrWhiteSpace(query))
            {
                string BingMapsKey = "YOUR_BING_MAPS_KEY";


                //string query2 = "http://dev.virtualearth.net/REST/v1/Elevation/List?key=" + BingMapsKey;
                //string content = "points=43.64856,-79.38532,43.64571,-79.3837,43.64549,-79.38329,43.64528,-79.38242,43.64221,-79.38119,43.64178,-79.38094,43.64164,-79.38124,43.64092,-79.38281,43.6402,-79.3847,43.63996,-79.38574,43.63917,-79.38974,43.63798,-79.39705,43.63806,-79.40244,43.63761,-79.40747,43.63753,-79.41111,43.63741,-79.41235,43.63701,-79.4141,43.63289,-79.42904,43.6326,-79.43056,43.63255,-79.43147,43.6326,-79.43263,43.63298,-79.43446,43.63718,-79.4444,43.63777,-79.44625,43.63826,-79.44821,43.6387,-79.45079,43.63899,-79.45365,43.63903,-79.45675,43.63881,-79.45921,43.6382,-79.46236,43.63766,-79.46423,43.63705,-79.46588,43.63566,-79.4691,43.63356,-79.47275,43.63234,-79.47506,43.63096,-79.47706,43.62868,-79.48003,43.62808,-79.48098,43.62767,-79.48191,43.62729,-79.48314,43.62483,-79.49312,43.62296,-79.50106,43.622,-79.50565,43.62187,-79.5067,43.61955,-79.51935,43.61877,-79.52279,43.61767,-79.5286,43.61687,-79.53189,43.61662,-79.53316,43.61537,-79.53966,43.61452,-79.54599,43.61409,-79.54801,43.61358,-79.54944,43.61265,-79.5512,43.61176,-79.55236,43.61,-79.55431,43.60972,-79.55462,43.59812,-79.56744,43.58361,-79.58315,43.57144,-79.59655,43.56412,-79.60442,43.56304,-79.60538,43.5545,-79.61161,43.55349,-79.61245,43.55291,-79.61304,43.55198,-79.61421,43.55143,-79.61508,43.55086,-79.61619,43.54962,-79.61905,43.54853,-79.62101,43.54799,-79.62183,43.54653,-79.62366,43.53446,-79.63682,43.52366,-79.64874,43.50242,-79.67183,43.50182,-79.67234,43.50074,-79.67304,43.49955,-79.67351,43.49885,-79.67367,43.49786,-79.67374,43.49064,-79.67337,43.49019,-79.67333,43.48675,-79.67307,43.4779,-79.6726,43.47686,-79.6726,43.47543,-79.67275,43.47332,-79.67332,43.47127,-79.67424,43.46977,-79.67524,43.46831,-79.67651,43.4573,-79.68833,43.45153,-79.69491,43.44795,-79.69865,43.44083,-79.70671,43.424,-79.72547,43.41362,-79.73681,43.40878,-79.74185,43.40359,-79.74774,43.38104,-79.77211,43.3507,-79.80551,43.34885,-79.80797,43.34739,-79.81046,43.34551,-79.81443,43.34138,-79.8236,43.3412,-79.82403,43.33999,-79.82682,43.33841,-79.82991,43.33687,-79.83315,43.33594,-79.83461,43.33359,-79.83767,43.33294,-79.83843,43.33008,-79.84133,43.31155,-79.86074,43.31057,-79.86189,43.30578,-79.8685,43.29793,-79.88123,43.29722,-79.88293,43.29493,-79.89009,43.29416,-79.8919,43.29329,-79.89305,43.29151,-79.8949,43.29116,-79.89526,43.29008,-79.89633,43.28898,-79.897,43.2879,-79.89727,43.28687,-79.89719,43.28593,-79.89682,43.28515,-79.89627,43.28272,-79.89359,43.28192,-79.89286,43.28106,-79.89241,43.28008,-79.89226,43.27869,-79.89242,43.27669,-79.89292,43.27616,-79.89298,43.27096,-79.89261,43.26284,-79.89332,43.26215,-79.8934,43.26155,-79.89358,43.26063,-79.89415,43.26022,-79.89457,43.25977,-79.8952,43.25933,-79.89618,43.25811,-79.90118,43.25772,-79.90248,43.257,-79.90416,43.25534,-79.90729,43.25494,-79.90853,43.25405,-79.91225,43.2535,-79.91366,43.25296,-79.91453,43.25236,-79.9152,43.25009,-79.91703,43.24946,-79.91766,43.24879,-79.91864,43.24835,-79.91965,43.24793,-79.92146,43.24605,-79.93524,43.24581,-79.93658,43.24546,-79.93784,43.24321,-79.94462,43.24289,-79.94548,43.24241,-79.94644,43.24204,-79.94699,43.24147,-79.94763,43.24083,-79.94813,43.24012,-79.9485,43.23895,-79.94873,43.23657,-79.94869,43.23587,-79.94875,43.23499,-79.94898,43.23388,-79.94956,43.23293,-79.95033,43.22665,-79.95622,43.21413,-79.96647,43.21354,-79.96694,43.21198,-79.96832,43.21034,-79.97019,43.20878,-79.97258,43.20781,-79.97451,43.20702,-79.97652,43.20614,-79.97976,43.20512,-79.986,43.20475,-79.98901,43.20467,-79.99126,43.20497,-80.00332,43.20518,-80.00463,43.20554,-80.00601,43.20723,-80.01023,43.20776,-80.01197,43.20803,-80.01317,43.2083,-80.01492,43.20846,-80.01688,43.20846,-80.01866,43.20833,-80.02036,43.20801,-80.0224,43.20766,-80.02383,43.19497,-80.06573,43.19411,-80.06914,43.19355,-80.07264,43.19328,-80.07662,43.19336,-80.08007,43.19411,-80.09108,43.19403,-80.0934,43.1937,-80.09567,43.19321,-80.09766,43.19258,-80.09932,43.18749,-80.10954,43.18692,-80.11081,43.18649,-80.11203,43.16948,-80.17784,43.16889,-80.18028,43.16856,-80.18218,43.1683,-80.18525,43.1674,-80.2215,43.16694,-80.23408,43.16682,-80.23565,43.16656,-80.23759,43.16463,-80.24739,43.16447,-80.24948,43.16457,-80.25124,43.1689,-80.28986,43.17152,-80.30633,43.17165,-80.3082,43.1716,-80.3101,43.16981,-80.32441,43.16638,-80.35039,43.16543,-80.35739,43.16475,-80.36152,43.15595,-80.4063,43.15289,-80.42296,43.1525,-80.42469,43.15184,-80.4272,43.15113,-80.42949,43.14668,-80.44093,43.14605,-80.44276,43.14503,-80.44631,43.14431,-80.44958,43.13224,-80.52956,43.13205,-80.53294,43.13228,-80.53653,43.13277,-80.53951,43.13737,-80.56417,43.13769,-80.56724,43.13765,-80.571,43.13719,-80.57461,43.13173,-80.61001,43.12506,-80.65866,43.12106,-80.68615,43.12088,-80.68859,43.12113,-80.6953,43.12117,-80.69615,43.12115,-80.69876,43.12081,-80.70133,43.12032,-80.70321,43.11862,-80.70826,43.11758,-80.71309,43.11733,-80.71468,43.11622,-80.72124,43.11579,-80.72291,43.11505,-80.72509,43.10779,-80.74117,43.10679,-80.74315,43.10511,-80.74601,43.0945,-80.76186,43.06917,-80.79636,43.05158,-80.82062,43.02543,-80.85702,43.0239,-80.85934,43.00426,-80.89054,43.00305,-80.89233,43.0017,-80.89413,42.98404,-80.91606,42.98316,-80.91729,42.98224,-80.91883,42.98142,-80.9205,42.9808,-80.92201,42.97996,-80.9248,42.97951,-80.92707,42.9722,-80.97529,42.95414,-81.08829,42.95352,-81.09099,42.95281,-81.09316,42.94605,-81.10856,42.94516,-81.11107,42.94462,-81.11321,42.94419,-81.11593,42.93905,-81.16608,42.93855,-81.16976,42.93788,-81.17317,42.9343,-81.1898,42.93142,-81.19948,42.93052,-81.20175,42.92972,-81.20335,42.92868,-81.20504,42.92712,-81.20707,42.90549,-81.2327,42.9042,-81.2341,42.90277,-81.23549,42.90049,-81.23742,42.83765,-81.28817,42.83503,-81.29061,42.83357,-81.29223,42.83241,-81.29366,42.81718,-81.31463,42.79505,-81.34727,42.77223,-81.37984,42.74959,-81.41189,42.73687,-81.4307,42.71835,-81.45532,42.69806,-81.48495,42.69077,-81.49529,42.67854,-81.51298,42.6386,-81.57114,42.63775,-81.57261,42.63702,-81.57414,42.63633,-81.57595,42.63575,-81.57792,42.63521,-81.58061,42.63252,-81.59895,42.63168,-81.60202,42.63102,-81.60376,42.6303,-81.60531,42.62946,-81.60681,42.62847,-81.6083,42.60921,-81.63612,42.59602,-81.65533,42.59511,-81.65694,42.59401,-81.65945,42.59338,-81.66131,42.59278,-81.66378,42.5924,-81.66657,42.5923,-81.66902,42.59252,-81.67264,42.59372,-81.68386,42.59381,-81.68615,42.59374,-81.68839,42.59351,-81.69044,42.593,-81.69305,42.59238,-81.69516,42.59136,-81.6977,42.59034,-81.69964,42.58944,-81.70104,42.55759,-81.74689,42.55681,-81.7481,42.556,-81.74958,42.55512,-81.75155,42.5546,-81.75301,42.55392,-81.75556,42.55062,-81.77467,42.55017,-81.77686,42.54966,-81.77868,42.54918,-81.78003,42.54867,-81.78125,42.54788,-81.78283,42.5463,-81.7854,42.51139,-81.83988,42.49445,-81.86506,42.49309,-81.86736,42.49243,-81.86877,42.49162,-81.87091,42.49081,-81.87415,42.48755,-81.89843,42.48712,-81.90095,42.48663,-81.90288,42.48623,-81.90412,42.48552,-81.9059,42.48492,-81.90716,42.4835,-81.90955,42.47109,-81.92843,42.45257,-81.95567,42.43808,-81.97642,42.41412,-82.01006,42.40536,-82.0227,42.39884,-82.03225,42.39814,-82.03348,42.39709,-82.03581,42.39616,-82.03863,42.38371,-82.08716,42.36143,-82.16479,42.36081,-82.16673,42.36008,-82.16852,42.35917,-82.17033,42.35326,-82.18097,42.35233,-82.18243,42.33821,-82.203,42.33744,-82.20427,42.33652,-82.20615,42.3354,-82.20922,42.32019,-82.26001,42.31821,-82.26671,42.31792,-82.2679,42.31752,-82.27006,42.31732,-82.27194,42.31661,-82.29035,42.31619,-82.29324,42.31575,-82.29508,42.3152,-82.29682,42.3044,-82.3238,42.30353,-82.3259,42.30279,-82.3274,42.30184,-82.32898,42.28293,-82.35732,42.2821,-82.35879,42.28146,-82.36013,42.28085,-82.36165,42.28031,-82.36335,42.27964,-82.36631,42.27934,-82.36911,42.27929,-82.37086,42.27947,-82.37734,42.27929,-82.38,42.26691,-82.45132,42.2662,-82.45374,42.26582,-82.45463,42.26519,-82.45579,42.26432,-82.45704,42.26204,-82.45972,42.26111,-82.46112,42.26044,-82.46235,42.25988,-82.46362,42.25929,-82.46528,42.25891,-82.46672,42.25858,-82.4685,42.25841,-82.47004,42.25835,-82.47177,42.25938,-82.49827,42.25928,-82.50094,42.25883,-82.50411,42.25842,-82.50584,42.25752,-82.50854,42.24396,-82.5441,42.2433,-82.54617,42.24276,-82.54883,42.24252,-82.55137,42.24252,-82.55294,42.24314,-82.5699,42.24302,-82.57271,42.24268,-82.57516,42.24213,-82.57755,42.24149,-82.57954,42.23369,-82.59891,42.23305,-82.60102,42.23253,-82.60348,42.23223,-82.60623,42.2322,-82.60934,42.23423,-82.66226,42.23455,-82.66756,42.23638,-82.69218,42.23651,-82.69479,42.23877,-82.80441,42.24082,-82.8736,42.2424,-82.93262,42.24269,-82.9355,42.24321,-82.93807,42.24359,-82.93942,42.24739,-82.95095,42.24785,-82.95323,42.24794,-82.95484,42.2479,-82.95643,42.24768,-82.95819,42.24584,-82.96551,42.24583,-82.96579,42.24534,-82.9688,42.24528,-82.97091,42.24555,-82.9732,42.24616,-82.97587,42.24641,-82.97701,42.24998,-82.99185,42.25115,-82.99758,42.25163,-82.99894,42.2524,-83.0002,42.25315,-83.00093,42.25718,-83.0038,42.27509,-83.01521,42.27599,-83.01589,42.28175,-83.01948,42.28225,-83.01971,42.28262,-83.01971,42.28297,-83.01961,42.28443,-83.01842,42.28462,-83.01831,42.28529,-83.01831,42.28566,-83.01849,42.29789,-83.02644,42.31756,-83.03905,42.31781,-83.03808,42.31851,-83.03524,42.31829,-83.03421,42.31782,-83.03392";

                //Uri request = new Uri(query2);

                //Response rx = await GetPOSTResponse(request, content);


                //Create the request URL for the Geocoding service
                Uri geocodeRequest = new Uri(
                    string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}",
                    query, BingMapsKey));

                //Make a request and get the response
                Response r = await GetResponse(geocodeRequest);

                if (r != null &&
                    r.ResourceSets != null &&
                    r.ResourceSets.Length > 0 &&
                    r.ResourceSets[0].Resources != null &&
                    r.ResourceSets[0].Resources.Length > 0)
                {
                    LocationCollection locations = new LocationCollection();

                    int i = 1;

                    foreach (BingMapsRESTService.Common.JSON.Location l in r.ResourceSets[0].Resources)
                    {
                        //Get the location of each result
                        Bing.Maps.Location location = new Bing.Maps.Location(l.Point.Coordinates[0], l.Point.Coordinates[1]);

                        //Create a pushpin each location
                        Pushpin pin = new Pushpin(){
                            Tag = l.Name,
                            Text = i.ToString()
                        };

                        i++;

                        //Add a tapped event that will display the name of the location
                        pin.Tapped += (s, a) =>
                        {
                            var p = s as Pushpin;
                            ShowMessage(p.Tag as string);
                        };

                        //Set the location of the pushpin
                        MapLayer.SetPosition(pin, location);

                        //Add the pushpin to the map
                        MyMap.Children.Add(pin);                      

                        //Add the coordinates of the location to a location collection
                        locations.Add(location);
                    }

                    //Set the map view based on the location collection
                    MyMap.SetView(new LocationRect(locations));

                    //Pass the results to the item source of the GeocodeResult ListBox
                    GeocodeResults.ItemsSource = r.ResourceSets[0].Resources;
                }
                else
                {
                    ShowMessage("No Results found.");
                }
            }
            else
            {
                ShowMessage("Invalid Geocode Input.");
            }
        }

        private async void RouteBtn_Click(object sender, RoutedEventArgs e)
        {
            ClearMap();

            string from = FromTbx.Text;
            string to = ToTbx.Text;            

            if (!string.IsNullOrWhiteSpace(from))
            {
                if (!string.IsNullOrWhiteSpace(to))
                {
                    //Create the Request URL for the routing service
                    Uri routeRequest = new Uri(
                        string.Format("http://dev.virtualearth.net/REST/V1/Routes/Driving?wp.0={0}&wp.1={1}&rpo=Points&key={2}", 
                        from, to, MyMap.Credentials));
                    
                    //Make a request and get the response
                    Response r = await GetResponse(routeRequest);

                    if (r != null &&
                        r.ResourceSets != null &&
                        r.ResourceSets.Length > 0 &&
                        r.ResourceSets[0].Resources != null &&
                        r.ResourceSets[0].Resources.Length > 0)
                    {
                        Route route = r.ResourceSets[0].Resources[0] as Route;

                        //Get the route line data
                        double[][] routePath = route.RoutePath.Line.Coordinates;
                        LocationCollection locations = new LocationCollection();

                        for (int i = 0; i < routePath.Length; i++)
                        {
                            if (routePath[i].Length >= 2)
                            {
                                locations.Add(new Bing.Maps.Location(routePath[i][0], routePath[i][1]));
                            }
                        }

                        //Create a MapPolyline of the route and add it to the map
                        MapPolyline routeLine = new MapPolyline()
                        {
                            Color = Colors.Blue,
                            Locations = locations,
                            Width = 5
                        };

                        routeLayer.Shapes.Add(routeLine);

                        //Add start and end pushpins
                        Pushpin start = new Pushpin()
                        {
                            Text = "S",
                            Background = new SolidColorBrush(Colors.Green)
                        };

                        MyMap.Children.Add(start);
                        MapLayer.SetPosition(start, 
                            new Bing.Maps.Location(route.RouteLegs[0].ActualStart.Coordinates[0], 
                                route.RouteLegs[0].ActualStart.Coordinates[1]));

                        Pushpin end = new Pushpin()
                        {
                            Text = "E",
                            Background = new SolidColorBrush(Colors.Red)
                        };

                        MyMap.Children.Add(end);
                        MapLayer.SetPosition(end, 
                            new Bing.Maps.Location(route.RouteLegs[0].ActualEnd.Coordinates[0], 
                            route.RouteLegs[0].ActualEnd.Coordinates[1]));

                        //Set the map view for the locations
                        MyMap.SetView(new LocationRect(locations));

                        //Pass the route to the Data context of the Route Results panel
                        RouteResults.DataContext = route;
                    }
                    else
                    {
                        ShowMessage("No Results found.");
                    }
                }
                else
                {
                    ShowMessage("Invalid 'To' location.");
                }
            }
            else
            {
                ShowMessage("Invalid 'From' location.");
            }
        }

        #endregion

        #region Private Methods

        private void ClearMap()
        {
            MyMap.Children.Clear();
            routeLayer.Shapes.Clear();

            //Clear the geocode results ItemSource
            GeocodeResults.ItemsSource = null;

            //Clear the route instructions
            RouteResults.DataContext = null;
        }

        private void GeocodeResultSelected(object sender, SelectionChangedEventArgs e)
        {
            var listBox = sender as ListBox;

            if (listBox.SelectedItems.Count > 0)
            {
                //Get the Selected Item
                var item = listBox.Items[listBox.SelectedIndex] as BingMapsRESTService.Common.JSON.Location;

                //Get the items location
                Bing.Maps.Location location = new Bing.Maps.Location(item.Point.Coordinates[0], item.Point.Coordinates[1]);

                //Zoom into the location
                MyMap.SetView(location, 18);
            }
        }

        private async Task<Response> GetResponse(Uri uri)
        {
            System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
            var response = await client.GetAsync(uri);

            using (var stream = await response.Content.ReadAsStreamAsync())
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
                return ser.ReadObject(stream) as Response;
            }
        }

        private async Task<Response> GetPOSTResponse(Uri uri, string data)
        {
            System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
            System.Net.Http.HttpContent content = new System.Net.Http.StringContent(data);

            var response = await client.PostAsync(uri, content);

            using (var stream = await response.Content.ReadAsStreamAsync())
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
                return ser.ReadObject(stream) as Response;
            }
        }

        private async void ShowMessage(string message)
        {
            MessageDialog dialog = new MessageDialog(message);
            await dialog.ShowAsync();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        #endregion
    }
}
